/*
 * safe_queue.h
 *
 *  Created on: 2008-12-28
 *      Author: ant
 */

#ifndef SAFE_QUEUE_H_
#define SAFE_QUEUE_H_

#include "condition.h"
#include "thread.h"
#include <queue>

BEGIN_NAMESPACE_TOXIC

// A generic thread-safe queue
template <typename T>
class safe_queue {
	CLASS_UNCOPYABLE(safe_queue)
public:
	safe_queue()
	:_isInterrupted(false) {

	}

	~safe_queue() {

	}

	bool empty() const {
		ScopedLock lock(_mutex);
		return _queue.empty();
	}

	size_t size() const {
		ScopedLock lock(_mutex);
		return _queue.size();
	}

	bool push(const T& value) {
		if (_isInterrupted) {
			return false;
		}
		ScopedLock lock(_mutex);
		_queue.push(value);
		lock.unlock();
		_notEmpty.notify();
		return true;
	}

	bool pop(T& value) {
		ScopedLock lock(_mutex);
		while (!_isInterrupted && _queue.empty()) {
			_notEmpty.wait(lock);
		}

		if (_isInterrupted && _queue.empty()) {
			return false;
		}

		value = _queue.front();
		_queue.pop();
		return true;
	}

	bool interrupt() {
		ScopedLock lock(_mutex);
		if (!_isInterrupted) {
			_isInterrupted = true;
			lock.unlock();
			_notEmpty.notifyAll();
			return true;
		}
		return false;
	}

private:
	Mutex _mutex;
	Condition _notEmpty;
	std::queue<T> _queue;
	volatile bool _isInterrupted;
};

END_NAMESPACE_TOXIC

#endif /* SAFE_QUEUE_H_ */
